from flask import Blueprint, request, jsonify, current_app
from werkzeug.security import generate_password_hash, check_password_hash
from datetime import datetime, timedelta
from flask_jwt_extended import create_access_token, jwt_required, get_jwt_identity, get_jwt
from functools import wraps
from database import db
from models import User, Role, Permission

auth_bp = Blueprint('auth', __name__)

# 辅助函数：获取当前用户
def get_current_user():
    user_id = get_jwt_identity()
    return User.query.get(user_id)

# 辅助函数：检查权限
def permission_required(permission):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            current_user = get_current_user()
            if not current_user or not current_user.has_permission(permission):
                return jsonify({'message': 'Permission denied!'}), 403
            return f(*args, **kwargs)
        return decorated_function
    return decorator

# 辅助函数：检查角色
def role_required(role):
    def decorator(f):
        @wraps(f)
        def decorated_function(*args, **kwargs):
            current_user = get_current_user()
            if not current_user or not current_user.has_role(role):
                return jsonify({'message': 'Role required!'}), 403
            return f(*args, **kwargs)
        return decorated_function
    return decorator

# 注册路由
@auth_bp.route('/register', methods=['POST'])
def register():
    data = request.get_json()

    # 检查必要字段
    if not data or not data.get('username') or not data.get('email') or not data.get('password'):
        return jsonify({'message': 'Missing required fields!'}), 400

    # 检查用户名是否已存在
    if User.query.filter_by(username=data['username']).first():
        return jsonify({'message': 'Username already exists!'}), 409

    # 检查邮箱是否已存在
    if User.query.filter_by(email=data['email']).first():
        return jsonify({'message': 'Email already exists!'}), 409

    # 创建新用户
    new_user = User(
        username=data['username'],
        email=data['email'],
        name=data.get('name', data['username'])
    )
    new_user.set_password(data['password'])

    # 如果是第一个用户，赋予管理员角色
    is_first_user = User.query.count() == 0
    if is_first_user:
        # 确保管理员角色存在
        admin_role = Role.query.filter_by(name='admin').first()
        if not admin_role:
            admin_role = Role(name='admin', description='Administrator role with all permissions')
            db.session.add(admin_role)
            db.session.flush()  # 刷新会话，获取ID但不提交

            # 创建基本权限
            permissions = [
                Permission(name='user_create', description='Create users'),
                Permission(name='user_read', description='Read users'),
                Permission(name='user_update', description='Update users'),
                Permission(name='user_delete', description='Delete users'),
                Permission(name='role_manage', description='Manage roles'),
                Permission(name='dashboard_access', description='Access dashboard')
            ]
            for perm in permissions:
                db.session.add(perm)
                admin_role.permissions.append(perm)

        new_user.roles.append(admin_role)

    # 保存到数据库
    db.session.add(new_user)
    db.session.commit()

    return jsonify({
        'message': 'User registered successfully!',
        'user': new_user.to_dict()
    }), 201

# 登录路由
@auth_bp.route('/login', methods=['POST'])
def login():
    data = request.get_json()

    # 检查必要字段
    if not data or not data.get('username') or not data.get('password'):
        return jsonify({'message': 'Missing username or password!'}), 400

    # 查找用户
    user = User.query.filter_by(username=data['username']).first()

    # 验证用户和密码
    if not user or not user.check_password(data['password']):
        return jsonify({'message': 'Invalid username or password!'}), 401

    # 检查用户状态
    if not user.is_active:
        return jsonify({'message': 'User account is disabled!'}), 401

    # 更新最后登录时间
    user.last_login = datetime.utcnow()
    db.session.commit()

    # 生成JWT令牌
    access_token = create_access_token(identity=user.id)

    return jsonify({
        'message': 'Login successful!',
        'token': access_token,
        'user': user.to_dict()
    }), 200

# 获取当前用户信息
@auth_bp.route('/me', methods=['GET'])
@jwt_required()
def get_me():
    current_user = get_current_user()
    return jsonify({
        'user': current_user.to_dict()
    }), 200

# 刷新令牌 - 不需要JWT验证
@auth_bp.route('/refresh', methods=['POST'])
def refresh_token():
    try:
        print("\n==== Refresh Token Request ====")
        print(f"Headers: {dict(request.headers)}")

        # 从请求中获取用户名和密码
        data = request.get_json()
        print(f"Refresh token request data: {data}")

        if not data or not data.get('username'):
            print("Missing username in refresh token request")
            return jsonify({'message': 'Missing username!'}), 400

        # 查找用户
        username = data.get('username')
        user = User.query.filter_by(username=username).first()

        if not user:
            print(f"User not found: {username}")
            return jsonify({'message': 'User not found!'}), 404

        # 生成新的JWT令牌
        access_token = create_access_token(identity=user.id)
        print(f"New token generated for user {user.username}")
        print("==== End of Refresh Token Request ====\n")

        return jsonify({
            'message': 'Token refreshed successfully!',
            'token': access_token,
            'user': user.to_dict()
        }), 200
    except Exception as e:
        import traceback
        print(f"Error in refresh_token: {str(e)}")
        print(traceback.format_exc())
        return jsonify({'message': f'An error occurred: {str(e)}'}), 500

# 修改密码 - 不需要JWT验证
@auth_bp.route('/change-password', methods=['POST'])
def change_password():
    try:
        # 打印请求头信息
        print("\n==== Change Password Request ====")
        print(f"Headers: {dict(request.headers)}")
        print(f"Data: {request.data}")

        data = request.get_json()
        print(f"Change password request data: {data}")

        # 检查必要字段
        if not data or not data.get('current_password') or not data.get('new_password'):
            print("Missing required fields in request data")
            return jsonify({'message': 'Missing required fields!'}), 400

        # 从请求中获取用户名
        username = data.get('username', 'admin')  # 默认使用admin用户
        print(f"Username from request: {username}")

        # 获取用户
        current_user = User.query.filter_by(username=username).first()
        print(f"Current user: {current_user.username if current_user else 'None'}")

        if not current_user:
            print("User not found in database!")
            return jsonify({'message': 'User not found!'}), 404

        # 验证当前密码
        current_password = data['current_password']
        print(f"Checking password: '{current_password}'")

        # 获取存储的密码哈希
        stored_password_hash = current_user.password_hash
        print(f"Stored password hash: {stored_password_hash}")

        # 验证密码
        password_correct = current_user.check_password(current_password)
        print(f"Current password validation result: {password_correct}")

        if not password_correct:
            print("Current password is incorrect")
            return jsonify({'message': 'Current password is incorrect!'}), 401

        # 更新密码
        new_password = data['new_password']
        print(f"Setting new password: '{new_password}'")
        current_user.set_password(new_password)
        db.session.commit()
        print(f"Password updated successfully for user {current_user.username}")
        print("==== End of Change Password Request ====\n")

        return jsonify({
            'message': 'Password changed successfully!'
        }), 200
    except Exception as e:
        import traceback
        print(f"Error in change_password: {str(e)}")
        print(traceback.format_exc())
        return jsonify({'message': f'An error occurred: {str(e)}'}), 500

# 用户管理路由 - 不需要认证
@auth_bp.route('/users', methods=['GET'])
def get_users():
    users = User.query.all()
    return jsonify({
        'users': [user.to_dict() for user in users]
    }), 200

@auth_bp.route('/users/<int:user_id>', methods=['GET'])
def get_user(user_id):
    user = User.query.get_or_404(user_id)
    return jsonify({
        'user': user.to_dict()
    }), 200

@auth_bp.route('/users/<int:user_id>', methods=['PUT'])
def update_user(user_id):
    user = User.query.get_or_404(user_id)
    data = request.get_json()

    # 更新用户信息
    if data.get('name'):
        user.name = data['name']
    if data.get('email'):
        # 检查邮箱是否已被其他用户使用
        existing_user = User.query.filter_by(email=data['email']).first()
        if existing_user and existing_user.id != user.id:
            return jsonify({'message': 'Email already in use!'}), 409
        user.email = data['email']
    if data.get('is_active') is not None:
        user.is_active = data['is_active']

    # 更新角色
    if data.get('roles'):
        # 清除现有角色
        user.roles = []
        # 添加新角色
        for role_name in data['roles']:
            role = Role.query.filter_by(name=role_name).first()
            if role:
                user.roles.append(role)

    db.session.commit()

    return jsonify({
        'message': 'User updated successfully!',
        'user': user.to_dict()
    }), 200

@auth_bp.route('/users/<int:user_id>', methods=['DELETE'])
def delete_user(user_id):

    user = User.query.get_or_404(user_id)
    db.session.delete(user)
    db.session.commit()

    return jsonify({
        'message': 'User deleted successfully!'
    }), 200

# 角色管理路由 - 不需要认证
@auth_bp.route('/roles', methods=['GET'])
def get_roles():
    roles = Role.query.all()
    return jsonify({
        'roles': [role.to_dict() for role in roles]
    }), 200

@auth_bp.route('/roles', methods=['POST'])
def create_role():
    data = request.get_json()

    # 检查必要字段
    if not data or not data.get('name'):
        return jsonify({'message': 'Missing required fields!'}), 400

    # 检查角色名是否已存在
    if Role.query.filter_by(name=data['name']).first():
        return jsonify({'message': 'Role name already exists!'}), 409

    # 创建新角色
    new_role = Role(
        name=data['name'],
        description=data.get('description', '')
    )

    # 添加权限
    if data.get('permissions'):
        for perm_name in data['permissions']:
            perm = Permission.query.filter_by(name=perm_name).first()
            if perm:
                new_role.permissions.append(perm)

    db.session.add(new_role)
    db.session.commit()

    return jsonify({
        'message': 'Role created successfully!',
        'role': new_role.to_dict()
    }), 201

@auth_bp.route('/roles/<int:role_id>', methods=['PUT'])
def update_role(role_id):
    role = Role.query.get_or_404(role_id)
    data = request.get_json()

    # 更新角色信息
    if data.get('name'):
        # 检查角色名是否已被其他角色使用
        existing_role = Role.query.filter_by(name=data['name']).first()
        if existing_role and existing_role.id != role.id:
            return jsonify({'message': 'Role name already in use!'}), 409
        role.name = data['name']
    if data.get('description') is not None:
        role.description = data['description']

    # 更新权限
    if data.get('permissions') is not None:
        # 清除现有权限
        role.permissions = []
        # 添加新权限
        for perm_name in data['permissions']:
            perm = Permission.query.filter_by(name=perm_name).first()
            if perm:
                role.permissions.append(perm)

    db.session.commit()

    return jsonify({
        'message': 'Role updated successfully!',
        'role': role.to_dict()
    }), 200

@auth_bp.route('/roles/<int:role_id>', methods=['DELETE'])
def delete_role(role_id):
    role = Role.query.get_or_404(role_id)

    # 检查是否有用户使用此角色
    if role.users:
        return jsonify({'message': 'Cannot delete role that is assigned to users!'}), 400

    db.session.delete(role)
    db.session.commit()

    return jsonify({
        'message': 'Role deleted successfully!'
    }), 200

# 权限管理路由 - 不需要认证
@auth_bp.route('/permissions', methods=['GET'])
def get_permissions():
    permissions = Permission.query.all()
    return jsonify({
        'permissions': [perm.to_dict() for perm in permissions]
    }), 200
